/**	\author    coidgen 0.9.2
	\version    (4.0 build 10)
	\date      
	\brief     
*/

#ifndef __COID_CLIENT__clientRegistrator_h
#define __COID_CLIENT__clientRegistrator_h


#define CLIENT__clientRegistrator_h



#include "coid/coidclient.h"
#include "coid/comm/sync/mutex_reg.h"


extern const version COID_version_ClientDatabase_4_0;


 
#include "coid/comm/binstream/stlstream.h"

 
struct birth_date
{
	int day;
	int month;
	int year;

	friend binstream & operator << ( binstream & out, const birth_date & x ) 	
	{ 
		return out << x.day << x.month << x.year; 
	};

    friend binstream & operator >> ( binstream & in, birth_date & x ) 
	{
		return in >> x.day >> x.month >> x.year;      /// notice the FIFO order (first in, first out)
    };

	friend metastream& operator << ( metastream& m, const birth_date & x )
    {
        MSTRUCT_OPEN(m,"birth_date");
		MM(m,"day",x.day);
		MM(m,"month",x.month);
		MM(m,"year",x.year);
		MSTRUCT_CLOSE(m);
    }
};

 
struct login_inf
{
	std::string login_name;
	std::string password;
	std::string retype_password;

	friend binstream & operator << ( binstream & out, const login_inf & x ) 	
	{ 
		return out << x.login_name << x.password << x.retype_password; 
	};

    friend binstream & operator >> ( binstream & in, login_inf & x ) 
	{
		return in >> x.login_name >> x.password >> x.retype_password;      /// notice the FIFO order (first in, first out)
    };

	friend metastream& operator << ( metastream& m, const login_inf & x )
    {
        MSTRUCT_OPEN(m,"login_inf");
		MM(m,"login_name",x.login_name);
		MM(m,"password",x.password);
		MM(m,"retype_password",x.retype_password);
		MSTRUCT_CLOSE(m);
    }

};

 
struct address_struct
{
	std::string street;
	std::string	city;
	std::string state;
	std::string zip;

	friend binstream & operator << ( binstream & out, const address_struct & x ) 	
	{ 
		return out << x.street << x.city << x.state << x.zip; 
	};

    friend binstream & operator >> ( binstream & in, address_struct & x ) 
	{
		return in >> x.street >> x.city >> x.state >> x.zip;      /// notice the FIFO order (first in, first out)
    };

	friend metastream& operator << ( metastream& m, const address_struct & x )
    {
        MSTRUCT_OPEN(m,"address");
		MM(m,"street",x.street);
		MM(m,"city",x.city);
		MM(m,"state",x.state);
		MM(m,"zip",x.zip);
		MSTRUCT_CLOSE(m);
    }

};

 
struct person
{
	std::string title;
	std::string name;
	std::string surname;
	address_struct address;
	login_inf login_information;
	birth_date birth_information;

	friend binstream & operator << ( binstream & out, const person & x ) 	
	{ 
		return out << x.title << x.name << x.surname << x.address << x.login_information << x.birth_information; 
	};

    friend binstream & operator >> ( binstream & in, person & x ) 
	{
		return in >> x.title  >> x.name >> x.surname >> x.address >> x.login_information >> x.birth_information;      /// notice the FIFO order (first in, first out)
    };

    friend metastream& operator << ( metastream& m, const person & x )
    {
        MSTRUCT_OPEN(m,"person");
		MM(m,"title",x.title);
		MM(m,"name",x.name);
		MM(m,"surname",x.surname);
		MM(m,"address",x.address);
		MM(m,"login_inforamtion",x.login_information);
		MM(m,"birth_information",x.birth_information);
        MSTRUCT_CLOSE(m);
    }

};




namespace coid {


struct COID_TABLE_ClientDatabase_4_0;


class ClientDatabase_client
{
private:
	COID_TABLE_ClientDatabase_4_0 * _me;
	COID_TABLE_ClientDatabase_4_0 * _vtbl;
	mutable comm_mutex_custom_reg<netstream, void*> _mx_reg;
	uint _conn_data;
	uint _timeout;
	charstr _addr;

	void set_connection_type( uint ct ) {_conn_data = ct;}
	void destroy_me();

public:
	ClientDatabase_client();
	~ClientDatabase_client();
	ClientDatabase_client( const ClientDatabase_client & c );
	ClientDatabase_client & operator = ( const ClientDatabase_client & c );

	opcd ping_server( const char * coid_address, uint coid_obj_id=UMAX, uint coid_flags=ConnectFlags::xACCESS_MODE ) const;
	bool is_connected() const {return _me != NULL;}
	opcd disconnect();
	const charstr& get_addr() const {return _addr;}
	comm_mutex_reg * get_mx() {return &_mx_reg;}
	opcd get_last_error() const;
	void set_last_error( opcd e );
	uint get_connection_type() const {return _conn_data;}
	opcd set_timeout( uint milliseconds );
	uint get_timeout() const {return _timeout;}
	void setup_stream( binstream& b, uint coid_flags, uint coid_obj_id ) const;
	bool setup_members( uint coid_stream_flags, netstream * bstream, binstream * bstream2=NULL, comm_mutex_reg * mx_reg=NULL );

	static const version & get_version() { return COID_version_ClientDatabase_4_0; }


public:
	opcd connect( std::vector< birth_date > & birt_d, const char * coid_address=NULL, uint coid_flags=ConnectFlags::xACCESS_MODE );
	opcd connect_within( comm_mutex_reg & coid_channel, std::vector< birth_date > & birt_d );
	opcd connect_shared( uint coid_obj_id,  const char * coid_address=NULL, uint coid_flags=ConnectFlags::xACCESS_MODE  );

	// sets personal data
	opcd add_user( person & person_in );
	opcd set_address( address_struct & address_in );
};

} // namespace coid


#endif	// ! __COID_CLIENT__clientRegistrator_h
